<script setup>
import newLoading from '@/components/newLoading/index.vue';
import Toast from "@vant/weapp/dist/toast/toast";
import myCanvas from '@/utils/myCanvas'
import { imgUploadVerify } from '@/utils/auth'
import { getCategoryDetail } from '@/api/home'
import { imgInpaint, editImgUpload, maskImgUpload, getImageByTaskId } from '@/api/painting'
import { ref, nextTick, computed } from 'vue'
import { onLoad, onReady, onUnload } from '@dcloudio/uni-app'

// 页面携带参数
const queryItem = ref({})
// 查询详情信息
const queryInfo = ref({})
// 页面参数
const queryParams = ref({})
// 提交数据
const queryData = ref({})
// 消耗算力
const expendNum = ref(0)


// 任务Id
const taskId = ref('')
let timer = null

// 是否加载状态
const loading = ref(false);
// 加载组件Ref
const loadingRef = ref(null);

// 画布实例
let imgCanvas, smearCanvas, eraseCanvas

// 原图尺寸
const oldImgSize = ref({})

// canvas盒子尺寸
const canvasBoxRect = ref({})
// canvas宽高
const imgRect = ref({})


// 绘图历史
const historyList = ref([]);
const historyIndex = ref(-1);

// 是否正在绘制(画笔)
const isDrawing = ref(false);
// 是否是橡皮擦模式
const isErase = ref(false);
// 橡皮擦位置
const eraserPosition = ref({ x: 0, y: 0 });
// 橡皮擦/线条大小
const sliderValue = ref(30)

// 记录上一个点
const lastPoint = ref({});

// 是否可以上一步
const lastStep = computed(() => historyIndex.value >= 1);

// 是否可以下一步
const nextStep = computed(() => historyIndex.value < historyList.value.length - 1);

// 开始消除
async function startFn() {
    clearInterval(timer);
    if (!queryParams.value.imageFileUrl) {
        return Toast.fail("请先上传修改图片");
    }
    if (!smearCanvas.hasDrawn(0, 0, smearCanvas.canvas.width, smearCanvas.canvas.height)) {
        return Toast.fail("请先进行涂抹消除");
    }
    // await exportCanvasImage()
    queryParams.value.imageMaskFileUrl = historyList.value[historyList.value.length - 1].url

    loading.value = true
    await editImgUploadFn()
    await maskImgUploadFn()
    imgInpaintFn()
}




// 获取任务状态
async function getImageByTaskIdFn() {
    const res = await getImageByTaskId(taskId.value)
    if (res.data.state === 1) {
        clearInterval(timer);
        await loadingRef.value.completeLoading()
        res.data.title = queryInfo.value.title
        queryData.value = res.data
        queryParams.value.imageFileUrl = res.data.imgPath

        historyList.value = historyList.value.filter(record => record.type !== 'smear');
        historyIndex.value = Math.min(historyIndex.value, historyList.value.length - 1);

        drawImageFn()
    } else if (![3, 4].includes(res.data.state)) {
        clearInterval(timer);
        const errorMessage = res.data.remark.split('失败原因：')[1]
        Toast.fail(errorMessage);
        loading.value = false
    }
}

// 图像消除任务提交
async function imgInpaintFn() {
    try {
        const res = await imgInpaint(queryData.value)
        taskId.value = res.data.taskId
        timer = setInterval(() => {
            getImageByTaskIdFn()
        }, 2000);

    } catch (error) {
        loading.value = false
        Toast.fail(error.data?.message);
    }
}


// 蒙版层图片上传
function maskImgUploadFn() {
    return new Promise(async (resolve, reject) => {
        try {
            const res = await maskImgUpload({
                orgImgUrl: queryData.value.imageFileUrl,
                maskType: 9,
                maskImg: queryParams.value.imageMaskFileUrl,
            })
            queryData.value.imageMaskFileUrl = res
            resolve()
        } catch (error) {
            loading.value = false
            reject()
        }
    })
}

// 上传原图
function editImgUploadFn() {
    return new Promise(async (resolve, reject) => {
        let url = ''
        if (queryParams.value.imageFileUrl.includes('https://')) {
            const res = await uni.getImageInfo({
                src: queryParams.value.imageFileUrl,
            })
            url = res.path
        } else {
            url = queryParams.value.imageFileUrl
        }

        try {
            const res = await editImgUpload({
                type: 2,
                orgImg: url
            })
            queryData.value.imageFileUrl = res.orgImgUrl
            resolve()
        } catch (error) {
            loading.value = false
            reject()
        }

    })

}

// 手指抬起
function touchend() {
    if (!isDrawing.value) return
    isDrawing.value = false;
    eraseCanvas.clearRect(0, 0, eraseCanvas.canvas.width, eraseCanvas.canvas.height)
    exportCanvas()
}


// 触摸移动
function touchmove(e) {
    if (!isDrawing.value) return
    const newPoint = e.touches[0]; // 记录当前点
    // 画笔
    if (!isErase.value) {
        smearCanvas.drawBrush(lastPoint.value.x, lastPoint.value.y, newPoint.x, newPoint.y, sliderValue.value, '#FFF')
    } else {
        smearCanvas.smoothErase(lastPoint.value.x, lastPoint.value.y, newPoint.x, newPoint.y, sliderValue.value)
    }
    eraseCanvas.clearRect(0, 0, eraseCanvas.canvas.width, eraseCanvas.canvas.height)
    eraseCanvas.drawRoundedRect(newPoint.x, newPoint.y, sliderValue.value, sliderValue.value / 2, 'rgba(0,0,0,0.5)')
    lastPoint.value = newPoint; // 更新上一个点
}


// 触摸事件
function touchstart(e) {
    if (!queryParams.value.imageFileUrl) return
    isDrawing.value = true;
    lastPoint.value = e.touches[0]; // 记录起点
    eraserPosition.value = {
        x: e.touches[0].x,
        y: e.touches[0].y
    }
}


// 上一步
function undo() {
    if (historyIndex.value > 0) {
        historyIndex.value--;
        restoreCanvas(historyList.value[historyIndex.value]);
    }
}

// 下一步
function redo() {
    if (historyIndex.value < historyList.value.length - 1) {
        historyIndex.value++;
        restoreCanvas(historyList.value[historyIndex.value]);
    }
}


// 恢复画布
function restoreCanvas(imageTemp) {
    if (imageTemp.type === 'img') {
        imgCanvas.drawImage(imageTemp.url, imageTemp.x, imageTemp.y, imageTemp.width, imageTemp.height, () => {
            imgCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height); // 清空画布
            smearCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height); // 清空画布
        });
    } else {
        smearCanvas.drawImage(imageTemp.url, imageTemp.x, imageTemp.y, imageTemp.width, imageTemp.height, () => {
            smearCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height); // 清空画布
        });
    }
}

// 导出当前画布为图片并存入历史记录
function exportCanvas(type = 'smear') {
    uni.canvasToTempFilePath({
        canvas: type === 'img' ? imgCanvas.canvas : smearCanvas.canvas,
        x: imgRect.value.x,
        y: imgRect.value.y,
        width: imgRect.value.width,
        height: imgRect.value.height,
        destWidth: oldImgSize.value.width,
        destHeight: oldImgSize.value.height,
        success: (res) => {
            // 如果有未来的历史记录，清除它们
            if (historyIndex.value < historyList.value.length - 1) {
                historyList.value.splice(historyIndex.value + 1);
            }
            uni.getImageInfo({
                src: res.tempFilePath,
                success: (res) => {
                    historyList.value.push({
                        type,
                        url: res.path,
                        x: imgRect.value.x, // 保存位置
                        y: imgRect.value.y, // 保存位置
                        width: imgRect.value.width, // 保存尺寸
                        height: imgRect.value.height // 保存尺寸
                    });
                    historyIndex.value++;
                }
            })
        }
    });
}

// 页面跳转
function toPage() {
    if (!queryData.value.imgPath) {
        return Toast.fail("请先进行消除");
    }

    uni.navigateTo({
        url: `/newEditionDraw/eliminate/detail/index?data=${JSON.stringify(queryData.value)}`
    })
}


// 清除历史记录
function clearHistory() {
    if (historyList.value.length > 0) {
        historyList.value = [historyList.value[0]]; // 保留初次绘图历史
        historyIndex.value = 0;
    } else {
        historyList.value = [];
        historyIndex.value = -1;
    }
    eraseCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height);
    smearCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height);
}

// 清除图片
function clearImg() {
    queryParams.value.imageFileUrl = ''
    queryData.value = {}
    imgCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height)
    smearCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height)
    historyList.value = [];
    historyIndex.value = -1;
}

// 是否是橡皮擦点击
function isEraseClickFn(e) {
    if (e === 1) {
        isErase.value = false
    } else {
        isErase.value = true
    }
}

// 调整橡皮擦线条大小
function sliderChange(e) {
    sliderValue.value = e.detail
}

// 调整橡皮擦线条大小
function sliderDrag(e) {
    sliderValue.value = e.detail.value
}

// 绘制图片
function drawImageFn() {
    imgCanvas.drawImage(queryParams.value.imageFileUrl, imgRect.value.x, imgRect.value.y, imgRect.value.width, imgRect.value.height,
        () => {
            imgCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height); // 清空画布
            smearCanvas.ctx.save()
            smearCanvas.clearRect(imgRect.value.x, imgRect.value.y, imgRect.value.width, imgRect.value.height, 'transparent');
            smearCanvas.drawRect(imgRect.value.x, imgRect.value.y, imgRect.value.width, imgRect.value.height, 'transparent');
            smearCanvas.ctx.clip()
        },
        () => {
            exportCanvas('img')
        });
}

// 上传图片
async function uplaodImgFn() {
    const res = await imgUploadVerify()
    queryParams.value.imageFileUrl = res

    calculatePicAspectRatio(queryParams.value.imageFileUrl).then(() => {
        drawImageFn()
    })
}


// 计算图片宽高比及外部边框盒子的宽高
async function calculatePicAspectRatio(path) {
    const { width, height } = await uni.getImageInfo({ src: path })

    const widthRatio = canvasBoxRect.value.width / width;
    const heightRatio = canvasBoxRect.value.height / height;
    const scaleRatio = Math.min(widthRatio, heightRatio);


    // 计算缩放后的图片宽度和高度
    const scaledWidth = width * scaleRatio;
    const scaledHeight = height * scaleRatio;

    oldImgSize.value = {
        width,
        height
    }

    imgRect.value = {
        width: scaledWidth,
        height: scaledHeight,
        x: (canvasBoxRect.value.width - scaledWidth) / 2,
        y: (canvasBoxRect.value.height - scaledHeight) / 2,
    }
}

// 加载关闭事件
function loadingClose() {
    clearInterval(timer);
}



// 获取分类详情
async function getCategoryDetailFn() {
    const res = await getCategoryDetail(queryItem.value.id)
    queryInfo.value = res.data
    dataConversion()
}


// 数据转换
function dataConversion() {
    queryInfo.value.categoryParam.forEach(item => {
        if (item.title === 'expendNum') {
            expendNum.value = item.data[0].title
        }
    })
}

onUnload(() => {
    clearInterval(timer);
    loading.value = false
})


onReady(() => {
    uni.createSelectorQuery().select('.canvas_box').boundingClientRect((res) => {
        canvasBoxRect.value.width = res.width
        canvasBoxRect.value.height = res.height
        imgCanvas = new myCanvas('imgCanvas')
        smearCanvas = new myCanvas('smearCanvas')
        eraseCanvas = new myCanvas('eraseCanvas')
    }).exec()
})

onLoad(async (e) => {
    if (e.item) {
        queryItem.value = JSON.parse(e.item)
        getCategoryDetailFn()

        if (!queryItem.value.imageFileUrl) return
        await nextTick()
        Toast.loading({
            message: '加载中...',
            duration: 0,
        })
        const res = await uni.getImageInfo({
            src: queryItem.value.imageFileUrl,
        })
        queryParams.value.imageFileUrl = res.path
        setTimeout(() => {
            imgCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height)
            smearCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height)
            eraseCanvas.clearRect(0, 0, canvasBoxRect.value.width, canvasBoxRect.value.height)
            calculatePicAspectRatio(queryParams.value.imageFileUrl).then(() => {
                drawImageFn()
                Toast.clear()
            })
        }, 600)
    }
})
</script>

<template>
    <div class='eliminate'>
        <NavBar :zIndex="5">{{ queryInfo?.title }}</NavBar>
        <div class="container">
            <div class="canvas_box">
                <!--上传按钮-->
                <div class="upload_btn" v-if="!queryParams?.imageFileUrl" @click="uplaodImgFn">
                    <i class="iconfont ai-icon-shangchuancankaotu"></i>
                    <div class="text">相册选择</div>
                </div>

                <!--删除-->
                <div v-else class="clearBox" @click="clearImg">
                    <i class="iconfont ai-icon-shanchutupian"></i>
                </div>

                <canvas type="2d" id="imgCanvas" class="imgCanvas"></canvas>
                <canvas type="2d" id="smearCanvas" class="smearCanvas"></canvas>

                <canvas type="2d" id="eraseCanvas" class="eraseCanvas" @touchstart="touchstart" @touchmove.stop="touchmove"
                    @touchend="touchend"></canvas>
            </div>
        </div>
        <div class="footer">
            <div class="footer_placeholder"></div>
            <div class="footer_content">
                <div class="eraser_top">
                    <div class="left" @click="clearHistory">
                        <i class="iconfont ai-icon-a-shibieleixingguanbi"></i>
                    </div>
                    <div class="center">
                        <i class="iconfont ai-icon-shangyibu" :class="{ active: lastStep }" @click="undo"></i>
                        <i class="iconfont ai-icon-xiayibu" :class="{ active: nextStep }" @click="redo"></i>

                    </div>
                    <div class="right" @click="toPage">
                        <i class="iconfont ai-icon-a-shibieleixingqueren"></i>
                    </div>
                </div>
                <div class="eraseAndsmear">
                    <div class="left">
                        <div class="smear" :class="{ active: !isErase }" @click="isEraseClickFn(1)">
                            <i class="iconfont ai-icon-tumo"></i>
                        </div>
                        <div class="erase" :class="{ active: isErase }" @click="isEraseClickFn(2)">
                            <i class="iconfont ai-icon-cachu"></i>
                        </div>
                    </div>
                    <div class="right">
                        <van-slider :value="sliderValue" :min="15" :max="45" @drag="sliderDrag" @change="sliderChange"
                            bar-height="4px" active-color="#83CD88" />
                    </div>
                </div>
                <div class="create_btn">
                    <myDrawButton :expendNum="expendNum" @click="startFn">开始消除</myDrawButton>
                </div>
            </div>
        </div>
    </div>
    <van-toast id="van-toast" />
    <newLoading ref="loadingRef" v-model="loading" :duration="10000" :label="['排队中，预计等待10秒']" @close="loadingClose">
    </newLoading>
</template>

<style lang='scss' scoped>
.eliminate {
    height: 100vh;
    display: flex;
    flex-direction: column;
    overflow: hidden;

    .container {
        flex: 1;
        padding: 30rpx;

        .canvas_box {
            position: relative;
            height: 100%;
            background: var(--a-main-box-bg-color);
            border-radius: 20rpx;
            overflow: hidden;

            .upload_btn {
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                z-index: 10;
                width: 228rpx;
                height: 84rpx;
                border-radius: 45rpx;
                border: 3rpx solid var(--a-main-color);
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 10rpx;

                .iconfont {
                    font-size: 32rpx;
                    color: var(--a-one-text-color);
                }

                .text {
                    font-size: 32rpx;
                    color: var(--a-one-text-color);
                }
            }

            .clearBox {
                position: absolute;
                bottom: 20rpx;
                right: 20rpx;
                z-index: 999;
                color: var(--a-one-text-color);
                width: 59rpx;
                height: 59rpx;
                background-color: #fff;
                background: rgba(0, 0, 0, 0.3);
                border-radius: 50%;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;

                .iconfont {
                    font-size: 36rpx;
                }

                .anewUpload {
                    font-size: 22rpx;
                }
            }

            .imgCanvas {
                z-index: 2;
            }

            .smearCanvas {
                z-index: 3;
            }

            .eraseCanvas {
                z-index: 4;
            }


            .bgCanvas,
            .imgCanvas,
            .smearCanvas,
            .eraseCanvas {
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
            }
        }
    }

    .footer {
        .footer_placeholder {
            height: 350rpx;
        }

        .footer_content {
            box-sizing: border-box;
            position: fixed;
            bottom: 0;
            left: 0;
            width: 100%;
            height: 350rpx;
            background: var(--a-main-tabNav-bg-color);
            padding: 28rpx 30rpx 30rpx;

            .eraser_top {
                display: flex;
                align-items: center;

                .left,
                .right {
                    flex-shrink: 0;
                    color: var(--a-one-text-color);

                    .iconfont {
                        font-size: 42rpx;
                    }
                }

                .center {
                    flex: 1;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: 98rpx;



                    .iconfont {
                        font-size: 56rpx;
                        color: #8a8a8a;

                        &.active {
                            color: var(--a-one-text-color);

                        }
                    }
                }
            }

            .eraseAndsmear {
                display: flex;
                align-items: center;
                gap: 26rpx;
                margin-top: 10rpx;

                .left {
                    flex-shrink: 0;
                    width: 170rpx;
                    height: 66rpx;
                    background: var(--a-main-box-bg-color);
                    border-radius: 33rpx;
                    display: flex;
                    align-items: center;
                    justify-content: center;

                    .smear,
                    .erase {
                        width: 82rpx;
                        height: 60rpx;
                        border-radius: 31rpx;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        color: var(--a-one-text-color);

                        .iconfont {
                            font-size: 32rpx;
                        }
                    }

                    .active {
                        background: var(--a-main-color);
                    }
                }

                .right {
                    flex: 1;
                }
            }

            .create_btn {
                margin-top: 40rpx;
            }


        }
    }
}
</style>